using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace AreaBuilder.Forms {
    public partial class frmProg : Form {
        private readonly AreaHolder ah;
        private readonly int existingVNum = -1;

        public frmProg() {
            InitializeComponent();
        }

        public frmProg(AreaHolder ah, int value) {
            InitializeComponent();

            this.ah = ah;
            existingVNum = value;
        }

        private void frmProg_Load(object sender, EventArgs e) {
            if (existingVNum >= 0) {
                MobProg mp = (from MobProg m in ah.area.Progs
                              where m.VNum == existingVNum
                              select m).Single();

                getMobsByProg(mp.VNum);
                txtVNum.Text = mp.VNum.ToString();
                txtProgram.Text = mp.Program.Replace("\n", Environment.NewLine);
                txtProgram.Indent();
            } else {
                if (getNextVnum() < 0) {
                    MessageBox.Show("VNum Range was incremented by 100.", "Hrm...", MessageBoxButtons.OK,
                                    MessageBoxIcon.Information);

                    ah.area.MaxVnum += 100;
                }

                txtVNum.Text = getNextVnum().ToString();
            }
        }

        private void getMobsByProg(int vnum) {
            IOrderedEnumerable<Mobile> query = from Mobile m in ah.area.Mobs
                                               orderby m.VNum
                                               select m;

            foreach (Mobile mob in query) {
                IOrderedEnumerable<MobProgLink> progs = from MobProgLink mpl in mob.Progs
                                                        where mpl.Program == vnum
                                                        orderby mpl.Program
                                                        select mpl;

#pragma warning disable 168
                foreach (MobProgLink mpl in progs)
                    lstMobs.Items.Add(String.Format("#{0} - {1}", mob.VNum, mob.Name));
#pragma warning restore 168
            }
        }

        private int getNextVnum() {
            int start = ah.area.MinVnum;
            int end = ah.area.MaxVnum;

            for (int i = start; i < end + 1; i++) {
                if (!validProgVnum(i))
                    return i;
            }

            return -1;
        }

        private bool validProgVnum(int vnum) {
            try {
#pragma warning disable 168
                MobProg mp = (from MobProg mobprog in ah.area.Progs
#pragma warning restore 168
                              where mobprog.VNum == vnum
                              select mobprog).Single();

                return true;
            } catch (InvalidOperationException) {}

            return false;
        }

        private void btnCancel_Click(object sender, EventArgs e) {
            Dispose();
        }

        private void btnOK_Click(object sender, EventArgs e) {
            MobProg mp = existingVNum >= 0 ? (from MobProg m in ah.area.Progs
                                              where m.VNum == existingVNum
                                              select m).Single() : new MobProg();

            mp.VNum = Int32.Parse(txtVNum.Text);
            mp.Program = txtProgram.Text;

            while (mp.Program.IndexOf("\r\r") >= 0)
                mp.Program = mp.Program.Replace("\r\r", "\r");

            if (existingVNum < 0)
                ah.area.Progs.Add(mp);

            Dispose();
        }

        private void btnPrev_Click(object sender, EventArgs e) {
            try {
                int currVnum = Int32.Parse(txtVNum.Text);
                IEnumerable<int> query = from MobProg mp in ah.area.Progs
                                         where mp.VNum < currVnum
                                         orderby mp.VNum descending
                                         select mp.VNum;
                int newArray = query.First();

                Form newForm = new frmProg(ah, newArray) { MdiParent = MdiParent };

                newForm.Location = new Point((MdiParent.Size.Width - newForm.Size.Width)/2 + 40,
                                             (MdiParent.Size.Height - newForm.Size.Height)/2 - 60);
                newForm.Show();

                btnOK_Click(null, null);
            } catch (Exception) {
                MessageBox.Show("There are no more mobprogs to show!", "Whoops!", MessageBoxButtons.OK,
                                MessageBoxIcon.Exclamation);
            }
        }

        private void btnNext_Click(object sender, EventArgs e) {
            try {
                int currVnum = Int32.Parse(txtVNum.Text);
                IEnumerable<int> query = from MobProg mp in ah.area.Progs
                                         where mp.VNum > currVnum
                                         orderby mp.VNum ascending
                                         select mp.VNum;
                int newArray = query.First();

                Form newForm = new frmProg(ah, newArray) { MdiParent = MdiParent };

                newForm.Location = new Point((MdiParent.Size.Width - newForm.Size.Width)/2 + 40,
                                             (MdiParent.Size.Height - newForm.Size.Height)/2 - 60);
                newForm.Show();

                btnOK_Click(null, null);
            } catch (Exception) {
                MessageBox.Show("There are no more mobprogs to show!", "Whoops!", MessageBoxButtons.OK,
                                MessageBoxIcon.Exclamation);
            }
        }

        private void btnIndent_Click(object sender, EventArgs e) {
            txtProgram.Indent();
        }
    }
}